package com.huawei.app.demo.service;

import java.lang.ref.WeakReference;

import android.app.Service;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.PixelFormat;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.util.DisplayMetrics;
import android.view.Display;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.Surface;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.ImageView;

import com.huawei.app.demo.MainActivity;
import com.huawei.app.demo.R;
import com.huawei.app.demo.fragment.VideoFragment;
import com.huawei.app.demo.video.AvcEncoderDecoderTask;
import com.huawei.app.demo.video.ShareScreenSurfaceCallback;

/**
 * 悬浮窗服务
 *
 * @since 2021-01-15
 */
public class VideoFloatingService extends Service {

    public static final int TYPE_CAPTURE_SCREEN = 1;
    public static final int TYPE_SHARE_SCREEN = 2;
    public static final int TYPE_SHARE_SCREEN_TO_REMOTE = 3;
    private int type = -1;

    // 截屏
    private View captureScreenRootView = null;
    private ImageView imageView = null;
    private Button captureBtn = null;
    private Button saveBtn = null;
    private Button cancelBtn = null;
    private Button quitBtn = null;

    // 共享屏幕
    private View shareScreenRootView = null;
    private View shareScreenSendRootView = null;

    private MyBinder binder = new MyBinder();

    public VideoFloatingService() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        this.type = intent.getIntExtra("type", -1);

        // 优先返回 binder, 业务逻辑放到延时 handler 中处理, 防止耗时太长导致 bind 失败
        Handler msgHandler = new Handler();
        msgHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                showFloatingWindow();
            }
        }, 200);
        return binder;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        this.type = intent.getIntExtra("type", -1);

        Handler tmpHandler = new Handler();
        tmpHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                showFloatingWindow();
            }
        }, 200);
        return super.onStartCommand(intent, flags, startId);
    }

    /**
     * 显示悬浮窗
     */
    public void showFloatingWindow() {
        if (type == TYPE_CAPTURE_SCREEN) {
            showCaptureScreenView();
        } else if (type == TYPE_SHARE_SCREEN) {
            showRecordScreenView();
        } else if (type == TYPE_SHARE_SCREEN_TO_REMOTE) {
            showShareScreenSendView();
        }
    }

    /**
     * 显示截屏界面
     */
    private void showCaptureScreenView() {
        LayoutInflater inflater = LayoutInflater.from(getApplicationContext());

        captureScreenRootView = inflater.inflate(R.layout.capture_screen_view, null);
        imageView = captureScreenRootView.findViewById(R.id.previewImg);
        captureBtn = captureScreenRootView.findViewById(R.id.doCaptureScreen);
        saveBtn = captureScreenRootView.findViewById(R.id.saveCaptureScreen);
        cancelBtn = captureScreenRootView.findViewById(R.id.cancelCaptureScreen);
        quitBtn = captureScreenRootView.findViewById(R.id.quitCaptureScreen);

        captureBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                binder.captureScreen();


            }
        });
        saveBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                binder.saveCaptureScreen();
            }
        });
        cancelBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                binder.cancelCaptureScreen();
            }
        });
        quitBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                binder.quitCaptureScreen();
            }
        });

        WindowManager.LayoutParams rootLayout = new WindowManager.LayoutParams();
        rootLayout.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
        rootLayout.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
        rootLayout.format = PixelFormat.RGBA_8888;
        rootLayout.gravity = Gravity.LEFT|Gravity.TOP;
        rootLayout.x = 0;
        rootLayout.y = getApplicationContext().getResources().getDisplayMetrics().heightPixels/2 - 50;
        rootLayout.width = ViewGroup.LayoutParams.WRAP_CONTENT;
        rootLayout.height = ViewGroup.LayoutParams.WRAP_CONTENT;

        WindowManager windowManager = (WindowManager)getSystemService(WINDOW_SERVICE);
        windowManager.addView(captureScreenRootView, rootLayout);
        captureBtn.setVisibility(View.VISIBLE);
        quitBtn.setVisibility(View.VISIBLE);

        captureScreenRootView.setOnTouchListener(new FloatingOnTouchListener(windowManager, rootLayout, captureScreenRootView));
        captureBtn.setOnTouchListener(new FloatingOnTouchListener(windowManager, rootLayout, captureScreenRootView));
        saveBtn.setOnTouchListener(new FloatingOnTouchListener(windowManager, rootLayout, captureScreenRootView));
        cancelBtn.setOnTouchListener(new FloatingOnTouchListener(windowManager, rootLayout, captureScreenRootView));
        quitBtn.setOnTouchListener(new FloatingOnTouchListener(windowManager, rootLayout, captureScreenRootView));
    }

    /**
     * 显示屏幕共享界面
     */
    private void showRecordScreenView() {
        LayoutInflater inflater = LayoutInflater.from(getApplicationContext());

        this.shareScreenRootView = inflater.inflate(R.layout.share_screen_view, null);
        Button stopBtn = shareScreenRootView.findViewById(R.id.stopShareScreen);
        stopBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                binder.stopShareScreen();
            }
        });

        WindowManager windowManager = (WindowManager)getSystemService(WINDOW_SERVICE);
        Display display = windowManager.getDefaultDisplay();
        DisplayMetrics realMetrics = new DisplayMetrics();
        display.getRealMetrics(realMetrics);
        int screenWidth = realMetrics.widthPixels;
        int screenHeight = realMetrics.heightPixels;

        // 准备编解码任务
        AvcEncoderDecoderTask shareScreenTask = new AvcEncoderDecoderTask(screenWidth, screenHeight, 30);
        Surface inputSurface = shareScreenTask.initEncoder();

        // 准备显示窗口
        SurfaceView shareScreenSurfaceview = shareScreenRootView.findViewById(R.id.shareScreenSurfaceview);
        shareScreenSurfaceview.getHolder().addCallback(new ShareScreenSurfaceCallback(shareScreenTask));

        WindowManager.LayoutParams rootLayout = new WindowManager.LayoutParams();
        rootLayout.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
        rootLayout.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
        rootLayout.format = PixelFormat.RGBA_8888;
        rootLayout.gravity = Gravity.LEFT|Gravity.TOP;
        rootLayout.x = screenWidth/2;
        rootLayout.y = screenHeight/2;
        rootLayout.width = screenWidth/2;
        rootLayout.height = screenHeight/2;
        shareScreenRootView.setOnTouchListener(new FloatingOnTouchListener(windowManager, rootLayout, shareScreenRootView));
        windowManager.addView(shareScreenRootView, rootLayout);

        binder.startShareScreen(screenWidth, screenHeight, realMetrics.densityDpi, inputSurface);
    }

    /**
     * 显示共享屏幕给远端界面
     */
    public void showShareScreenSendView() {
        LayoutInflater inflater = LayoutInflater.from(getApplicationContext());

        this.shareScreenSendRootView = inflater.inflate(R.layout.share_screen_sender_view, null);
        Button stopBtn = shareScreenSendRootView.findViewById(R.id.shareScreenSendStopBtn);
        stopBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                binder.stopShareScreenSend();
            }
        });

        WindowManager windowManager = (WindowManager)getSystemService(WINDOW_SERVICE);
        Display display = windowManager.getDefaultDisplay();
        DisplayMetrics realMetrics = new DisplayMetrics();
        display.getRealMetrics(realMetrics);
        int screenWidth = realMetrics.widthPixels;
        int screenHeight = realMetrics.heightPixels;

        WindowManager.LayoutParams rootLayout = new WindowManager.LayoutParams();
        rootLayout.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
        rootLayout.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
        rootLayout.format = PixelFormat.RGBA_8888;
        rootLayout.gravity = Gravity.LEFT|Gravity.TOP;
        rootLayout.x = screenWidth/2 - 200;
        rootLayout.y = screenHeight - 135;
        rootLayout.width = 400;
        rootLayout.height = 135;
        shareScreenSendRootView.setOnTouchListener(new FloatingOnTouchListener(windowManager, rootLayout, shareScreenSendRootView));
        stopBtn.setOnTouchListener(new FloatingOnTouchListener(windowManager, rootLayout, shareScreenSendRootView));
        windowManager.addView(shareScreenSendRootView, rootLayout);

        binder.startShareScreenSend();
    }

    @Override
    public void onDestroy() {
        WindowManager windowManager = (WindowManager)getSystemService(WINDOW_SERVICE);
        if (captureScreenRootView != null) {
            windowManager.removeView(captureScreenRootView);
        }
        if (shareScreenRootView != null) {
            windowManager.removeView(shareScreenRootView);
        }
        if (shareScreenSendRootView != null) {
            windowManager.removeView(shareScreenSendRootView);
        }
        super.onDestroy();
    }

    public class MyBinder extends Binder {
        private WeakReference<VideoFragment> contextRef = null;
        private Bitmap currentBitmap;

        public void setContext(VideoFragment videoFragment) {
            this.contextRef = new WeakReference<>(videoFragment);
        }

        /**
         * 截屏
         */
        public void captureScreen() {
            if (!isConnected()) {
                return;
            }

            // 截屏之前需要把按钮隐藏, 否则会把按钮一起截屏
            captureBtn.setVisibility(View.GONE);
            quitBtn.setVisibility(View.GONE);
            contextRef.get().captureScreen();
        }

        /**
         * 保存截屏
         */
        public void saveCaptureScreen() {
            if (!isConnected()) {
                return;
            }
            contextRef.get().saveCaptureScreen(currentBitmap);
            cancelCaptureScreen();
        }

        /**
         * 撤销截屏
         */
        public void cancelCaptureScreen() {
            imageView.setImageDrawable(null);
            currentBitmap = null;

            ViewGroup.LayoutParams imgLayout = imageView.getLayoutParams();
            imgLayout.width = 0;
            imgLayout.height = 0;
            imageView.setLayoutParams(imgLayout);

            WindowManager windowManager = (WindowManager)getSystemService(WINDOW_SERVICE);
            WindowManager.LayoutParams rootViewLayout = (WindowManager.LayoutParams)captureScreenRootView.getLayoutParams();
            rootViewLayout.x = 0;
            rootViewLayout.y = getApplicationContext().getResources().getDisplayMetrics().heightPixels/2 - 50;
            windowManager.updateViewLayout(captureScreenRootView, rootViewLayout);

            captureBtn.setVisibility(View.VISIBLE);
            saveBtn.setVisibility(View.GONE);
            cancelBtn.setVisibility(View.GONE);
            quitBtn.setVisibility(View.VISIBLE);
        }

        /**
         * 退出截屏
         */
        public void quitCaptureScreen() {
            if (!isConnected()) {
                return;
            }
            contextRef.get().stopFloatingService();
        }

        /**
         * 预览图像
         * @param bitmap
         */
        public void previewScreenshot(Bitmap bitmap) {
            imageView.setImageBitmap(bitmap);
            this.currentBitmap = bitmap;

            DisplayMetrics metrics = getResources().getDisplayMetrics();
            float ratio = (1.0f * bitmap.getWidth()) / bitmap.getHeight();

            ViewGroup.LayoutParams imgLayout = imageView.getLayoutParams();
            imgLayout.width = Math.round(metrics.widthPixels * 0.8f);
            imgLayout.height = Math.round(imgLayout.width / ratio);
            imageView.setLayoutParams(imgLayout);

            WindowManager windowManager = (WindowManager)getSystemService(WINDOW_SERVICE);
            WindowManager.LayoutParams rootViewLayout = (WindowManager.LayoutParams)captureScreenRootView.getLayoutParams();
            rootViewLayout.x = (metrics.widthPixels - imgLayout.width)/2;
            rootViewLayout.y = (metrics.heightPixels - imgLayout.height)/2;
            windowManager.updateViewLayout(captureScreenRootView, rootViewLayout);

            saveBtn.setVisibility(View.VISIBLE);
            cancelBtn.setVisibility(View.VISIBLE);
            quitBtn.setVisibility(View.VISIBLE);
        }

        /**
         * 开始共享屏幕
         * @param width
         * @param height
         * @param dpi
         * @param inputSurface
         */
        public void startShareScreen(int width, int height, int dpi, Surface inputSurface) {
            int count = 0;
            while (!isConnected() && count < 30) {
                try {
                    count++;
                    Thread.sleep(100);
                } catch (Exception e) {
                    // ignore.
                }
            }

            if (!isConnected()) {
                return;
            }
            contextRef.get().startShareScreen(width, height, dpi, inputSurface);
        }

        /**
         * 停止共享屏幕
         */
        public void stopShareScreen() {
            if (!isConnected()) {
                return;
            }
            contextRef.get().stopShareScreen();
            contextRef.get().stopFloatingService();
        }

        /**
         * 开始共享屏幕给远端
         */
        public void startShareScreenSend() {
            int count = 0;
            while (!isConnected() && count < 30) {
                try {
                    count++;
                    Thread.sleep(100);
                } catch (Exception e) {
                    // ignore.
                }
            }

            if (!isConnected()) {
                return;
            }
            contextRef.get().startShareScreenSend();
        }

        /**
         * 停止共享屏幕给远端
         */
        public void stopShareScreenSend() {
            if (!isConnected()) {
                return;
            }
            contextRef.get().stopShareScreenSend();
            contextRef.get().stopFloatingService();
        }

        public boolean isConnected() {
            return (contextRef != null && contextRef.get() != null);
        }
    }
}
